
import os
import stat
from StringIO import StringIO
from zipfile import ZipFile, ZipInfo

#===============================================================================
# The decorator function
#===============================================================================
from threading import Lock
lock = Lock() # TODO: locking
def synchronized(f):
    """A decorator to synchronize all accesses from remote clients.
    
    This decorator function is specifically used to protect read/write acceses 
    to the globally shared'tasks' data. Any service method accesses 'tasks'
    should be decorated.
    
    """
    def new(*args, **kwargs):
        try:
            lock.acquire()
            res = f(*args, **kwargs)
            return res
        finally:
            lock.release()
    return new

#===============================================================================
# Helper functions
#===============================================================================
def rmentry(entry):
    if os.path.isdir(entry):
        del_tree(entry)
        os.rmdir(entry)
    elif os.path.isfile(entry):
        os.remove(entry)
    else:
        pass #ERROR
        
def del_tree(path):
    " Delete all the directory structure, could be very dangerous "
    " Does not delete root folder"
    for root, dirs, files in os.walk(path, topdown=False):
#        if root[0] == '.' :
#            continue
        for name in files:
            os.remove(os.path.join(root,name))
        for name in dirs:
            os.rmdir(os.path.join(root,name))

def unzip(zip_file_content , output_dir , mode='d'):
    """ 
    Unzip the zip_file_content in output-dir
    If the output_dir does not exist, it will create it first
    mode : 'd' to delete every thing in the output directory before extraction
           'i' do not write on the existing files in the output-directory
           'o' overwrite on the existing file and ignore rest of files and directories
    """
    
    if not os.path.exists(output_dir):
        os.mkdir(output_dir)
    
    zip_file = StringIO(zip_file_content)
    contents = ZipFile(zip_file, 'r')
    
    output_dir += "/"
    base_dir = output_dir

    if mode=="d" :
        del_tree(output_dir)
    
    for file in contents.namelist():
        file_dir = os.path.join(base_dir, os.path.dirname(file.replace('/', os.sep)))
        file_name = os.path.basename(file)
        file_path = os.path.join(base_dir, file.replace('/', os.sep))
        #print file, "!", file_name, "!", file_path, "<br><br>"
        if not os.path.exists(file_dir):
            os.makedirs(file_dir)
            writeable(file_dir)
        data = contents.read(file)
        try:
            fp = open(file_path, 'wb')
            fp.write(data)
            fp.close()
            if file.endswith("py"):
                # give read and execute permission to file
                writeable(file_path)
        except IOError:
            pass # XXX handle permissions    

def writeable(file):
    """
    Make writeable by other users
    """
    try:
        os.chmod(file, stat.S_IRWXU | stat.S_IRWXG | stat.S_IRWXO)#stat.S_IRGRP | stat.S_IXGRP | stat.S_IROTH | stat.S_IXOTH)
    except OSError:
        pass # insufficient permissions

ZIP_NAME = "temp.zip"

def get_schema_zip(schema_dir):
    prev_path = os.getcwd()
    z = ZipFile(ZIP_NAME, "w")

    os.chdir(schema_dir)  
    for root, dirs, files in os.walk("."):
        if root.find(".svn") != -1:
            continue       
        #print root, dirs, files
        for file in files:
            if not file.endswith(".pyc") and file != ZIP_NAME:
                z.write(os.path.join(root, file))  
        for dir in dirs:
            if dir != ".svn":   
                z.write(os.path.join(root, dir))
    os.chdir(prev_path)
    z.close()
    f = open(ZIP_NAME, "rb")
    data = f.read()
    f.close()
    #os.remove(filename)
    return data


# TODO: have to synch the methods
class NameMgr(object):
    def __init__(self, prefix):
        self.prefix = prefix
        self.cnt = 1 # shows the current available no
        self.released = {}
        self.allocated = {}

    def _generate_name(self, cnt):
        return self.prefix + str(cnt)
    
    def get_name(self):
        if len(self.released) == 0:
            name = self._generate_name(self.cnt)
            self.cnt += 1
            self.allocated[name] = None
        else:
            name = self.released.keys()[0]
            assert not self.allocated.has_key(name)
            self.allocated[name] = None
            del self.released[name]
        return name
    
    def release_name(self, name):
        assert self.allocated.has_key(name)
        assert not self.released.has_key(name)
        del self.allocated[name]
        self.released[name] = None

#===============================================================================
# Testing with main
#===============================================================================
def main():
    #unzip_file_into_dir("input5.zip", "veli")
    #del_tree("veli")
    pass
    
if __name__ == '__main__': 
    main()
